package com.ctrip.cap.device.ios.impl;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Locale;

import org.apache.commons.exec.CommandLine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ctrip.cap.common.shell.ShellCommand;
import com.ctrip.cap.common.shell.exception.ShellCommandException;
import com.ctrip.cap.device.ios.IOSDevice;
import com.ctrip.cap.device.model.DeviceInfo;

/**
 * @author zwxu
 *
 */

public class IPhoneDevice implements IOSDevice, Comparable<IPhoneDevice> {
	private static final Logger logger = LoggerFactory
			.getLogger(IPhoneDevice.class);
	private static final Integer COMMAND_TIMEOUT = 20000;
	private String serial = null;
	private String fruitstrap = "/usr/local/lib/node_modules/appium/build/fruitstrap/fruitstrap";
	private String libPath = "/usr/local/bin/";

	public IPhoneDevice(String udid) {
		this.serial = udid;
	}

	@Override
	public int compareTo(IPhoneDevice o) {
		return this.serial.compareTo(o.serial);
	}

	@Override
	public String getSerialNumber() {
		return serial;
	}

	@Override
	public Locale getLocale() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void tap(int x, int y) {
		// TODO Auto-generated method stub

	}

	@Override
	public void swipe(int x1, int y1, int x2, int y2) {
		// TODO Auto-generated method stub
	}

	@Override
	public void install(String appFullPath) {
		logger.info("Beginning to install App on device: " + serial);
		String cmd = fruitstrap + " install --id " + serial + " --bundle "
				+ appFullPath;

		executeCommand(cmd);
		logger.info("Finish to install App on device: " + serial);
	}

	@Override
	public void uninstall(String bundleID) {
		logger.info("Beginning to uninstall App on device: " + serial);
		String cmd = fruitstrap + " uninstall --id " + serial + " --bundle "
				+ bundleID;

		executeCommand(cmd);
		logger.info("Finish to uninstall App on device: " + serial);
	}

	@Override
	public boolean isInstalled(String bundleID) {
		logger.info("Check: Does app exist on device: " + serial);
		String cmd = fruitstrap + " isInstalled --id " + serial + " --bundle "
				+ bundleID;
		Process process = null;
		try {
			process = Runtime.getRuntime().exec(cmd);

			try {
				process.waitFor();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (process.exitValue() == 0) {
				logger.info("App already exists on device: " + serial);
				return true;
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			process.destroy();
		}

		logger.info("App doesn't exist on device: " + serial);
		return false;
	}

	@Override
	public boolean start(String bundleID) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void kill(String bundleID) {
		// TODO Auto-generated method stub

	}

	@Override
	public DeviceInfo getDeviceInfo() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isDeviceReady() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean isScreenOn() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void unlock() {
		// TODO Auto-generated method stub

	}

	@Override
	public String getName() {
		return executeCommandQuietly(ideviceCommand("-u", serial, "-k",
				"DeviceName"));
	}

	@Override
	public String getPlatformVersion() {
		return executeCommandQuietly(ideviceCommand("-u", serial, "-k",
				"ProductVersion"));
	}

	@Override
	public void clearUserData(String bundleID) {
		// TODO Auto-generated method stub

	}

	@Override
	public void takeScreenshot(String fileUrl) {
		String cmd = libPath + "idevicescreenshot -u " + serial + " " + fileUrl;
		executeCommand(cmd);
	}

	@Override
	public void inputKeyevent(int value) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean isWifiOff() {
		// TODO Auto-generated method stub
		return false;
	}

	protected Boolean executeCommand(String cmdStr) {

		Process process = null;
		String line = null;
		try {
			process = Runtime.getRuntime().exec(cmdStr);
			BufferedReader stdout = new BufferedReader(new InputStreamReader(
					process.getInputStream()));
			while ((line = stdout.readLine()) != null) {
				logger.info(line);
			}

			process.waitFor();

			if (process.exitValue() == 0) {
				return true;
			}
		} catch (IOException e) {
			String logMessage = String.format("Could not execute command: %s",
					cmdStr);
			logger.warn(logMessage, e);
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			process.destroy();
		}

		return false;
	}

	protected String executeCommandQuietly(CommandLine command) {
		return executeCommandQuietly(command, COMMAND_TIMEOUT);
	}

	protected String executeCommandQuietly(CommandLine command, long timeout) {
		try {
			return ShellCommand.exec(command, timeout).trim();
		} catch (ShellCommandException e) {
			String logMessage = String.format("Could not execute command: %s",
					command);
			logger.warn(logMessage, e);
			return "";
		}
	}

	private CommandLine ideviceCommand() {
		CommandLine command = new CommandLine(new File(libPath + "ideviceinfo"));
		return command;
	}

	private CommandLine ideviceCommand(String... args) {
		CommandLine command = ideviceCommand();
		for (String arg : args) {
			command.addArgument(arg, false);
		}
		return command;
	}

	@Override
	public BufferedImage takeScreenshot() {
		// TODO Auto-generated method stub
		return null;
	}
}